#ifndef __COROUTINE_SCHEDULER_TASK_H__
#define __COROUTINE_SCHEDULER_TASK_H__

#include <mutex>
#include <thread>
#include <iostream>
#include <queue>

#include <coroutine>


namespace coroutine_scheduler_task
{
	/*
	杨花落尽子规啼，闻道龙标过五溪。
	我寄愁心与明月，随君直到夜郎西。
	*/

	std::mutex mutex;

	void printNmber_thread()
	{
		for (int i = 0; i < 10; ++i)
		{
			std::lock_guard<std::mutex> lock(mutex);
			std::cout << i << " ";
		}

		std::cout << std::endl;
	}

	void printLetters_thread()
	{
		for (char c = 'a'; c <= 'z'; ++c)
		{
			std::lock_guard<std::mutex> lock(mutex);
			std::cout << c << " ";
		}

		std::cout << std::endl;
	}

	// 任务结构体，包含协程句柄和任务函数
	struct Task
	{
		struct promise_type;
		using cor_pomise = std::coroutine_handle<promise_type>;

		Task(cor_pomise h)
			: m_coro_promies{ h }
		{
			std::cout << __func__ << std::endl;
		}

		~Task()
		{
			if (m_coro_promies != nullptr)
			{
				std::cout << __func__ << std::endl;
				m_coro_promies.destroy();
			}
		}

		struct promise_type
		{
			auto get_return_object()
			{
				return Task{ cor_pomise::from_promise(*this) };
			}

			std::suspend_always initial_suspend()
			{
				return std::suspend_always{};
			}

			std::suspend_always final_suspend() noexcept
			{
				return std::suspend_always{};
			}

			void unhandled_exception() { std::terminate(); }

			void return_void() {}
		};

		//
		cor_pomise m_coro_promies;
	};

	// 简单的协程调度器(程序有错误)
	class Scheduler
	{
	public:
		void schedule(Task task)
		{
			std::cout << __func__ << std::endl;
			tasks.push(task);
		}

		void run()
		{
			std::cout << __func__ << std::endl;
			while (!tasks.empty())
			{
				Task current = tasks.front();
				std::cout << "front()" << std::endl;

				tasks.pop();
				std::cout << "pop()" << std::endl;

				current.m_coro_promies.resume();
				std::cout << "resume()" << std::endl;

				if (!current.m_coro_promies.done())
				{
					tasks.push(current);
					std::cout << "push()" << std::endl;
				}
			}
		}

	private:
		std::queue<Task> tasks;
	};

	// 打印数字的协程函数
	Task printNumbers()
	{
		std::cout << __func__ << std::endl;
		for (int i = 0; i < 10; ++i)
		{
			std::cout << i << " ";

			co_await std::suspend_always{};
		}

		co_return;
	}

	// 打印字母的协程函数
	Task printLetters()
	{
		std::cout << __func__ << std::endl;
		for (char c = 'a'; c < 'z'; ++c)
		{
			std::cout << c << " ";

			co_await std::suspend_always{};
		}

		co_return;
	}

	int test()
	{
		{ // test_thread
			std::cout << "打印数字和字符的多线程版本" << std::endl;

			std::thread t1(printNmber_thread);
			std::thread t2(printLetters_thread);

			t1.join();
			t2.join();
		}

		std::cout << std::endl;

		{ // test_coroutine
			std::cout << "打印数字和字符的协程版本" << std::endl;

			Scheduler scheduler;

			scheduler.schedule(printNumbers());
			scheduler.schedule(printLetters());

			scheduler.run();
		}

		std::cout << std::endl;

		return 0;
	}
}

#endif